;all commands CLS ;clear screen cls RET ;return from subroutine return JP label ;jump to address jump CALL label ;jump to subroutine at address call SE V0, #01 ;skip next instruction if Vx is value sei SNE V0, #01 ;skip next instruction if Vx is not value snei SE V0, V1 ;skip next instruction if Vx is Vy ser LD V0, #01 ;load Vx with value movi ADD V0, #01 ;add value to Vx addi LD V0, V1 ;load Vy in Vx movr OR V0, V1 ;bitwise OR Vx with Vy or AND V0, V1 ;bitwise AND Vx with Vy and XOR V0, V1 ;bitwise XOR Vx with Vy xor ADD V0, V1 ;add Vy to Vx, carry in Vf addr SUB V0, V1 ;subtract Vy from Vx, borrow-bit in Vf subr SHR V0, {V1} ;shift Vx right one, removed bit in Vf, Vy unused shr SUBN V0, V1 ;subtract Vx from Vy, store in Vx, borrow-bit in Vf nsubr SHL V0, {V1} ;shift Vx left one, removed bit in Vf, Vy unused shl SNE V0, V1 ;skip next instruction if Vx is not Vy sner LD I, label ;load I with address from label imovi JP V0, label ;jump to address added with V0 (only V0) jumpoff RND V0, #01 ;load Vx with random value AND-ed with value rnd DRW V0, V1, #1 ;draw at (Vx, Vy) a value (0-15) high sprite with data from I sprite SKP V0 ;skip next instruction if key in Vx is pressed skr SKNP V0 ;skip next instruction if key in Vx is not pressed snkr LD V0, DT ;load Vx with delay timer rmovt LD V0, K ;halt execution until key is pressed, load Vx with pressed key waitk LD DT, V0 ;load delay timer with Vx movt LD ST, V0 ;load sound timer with Vx movs ADD I, V0 ;add Vx to I iaddr LD F, V0 ;load I with address for hex-digit sprite for Vx digit LD B, V0 ;load value at I, I+1, I+2 with BCD for Vx bcd LD [I], V1 ;load memory at I - I+x with V0 - Vx store LD V1, [I] ;load V0 - Vx with memory at I - I+x load ;;;;;;;; ; MAZE ; ;;;;;;;; mainLoop: LD I, tile2 ;load I with address for diagonal line RND V2, #01 ;generate a random value from 0 to 1 in V2 SE V2, #01 ;if that value is not 1... LD I, tile1 ;change I to address for diagonal line the other way. DRW V0, V1, #4 ;draw at (xpos, ypos) a 4 high sprite from I ADD V0, #04 ;increment xpos by 4 SE V0, #40 ;if xpos is not and end of row... JP mainLoop ;jump back to beginning, else... LD V0, #00 ;reset xpos to start ADD V1, #04 ;increment ypos by 4 SE V1, #20 ;if ypos is not at end of screen... JP mainLoop ;jump back to beginning, else... infLoop: JP infLoop ;go in a infinite loop tile1: #80 ;10000000 #40 ;01000000 #20 ;00100000 #10 ;00010000 tile2: #20 ;00100000 #40 ;01000000 #80 ;10000000 #10 ;00010000 ;end of rom ;;;;;;;;;;;; ; CONNECT4 ; ;;;;;;;;;;;; JP start ;start game #43 ;"CONNECT4 by David WINTER" #4f ; #4e ; #4e ; #45 ; #43 ; #54 ; #34 ; #20 ; #62 ; #79 ; #20 ; #44 ; #61 ; #76 ; #69 ; #64 ; #20 ; #57 ; #49 ; #4e ; #54 ; #45 ; #52 ; start: LD I, stnStart ;address for initial stack state LD V6, [I] ;load v0 to v6 with values for initial stack height LD I, stnState ;address for stack state LD [I], V6 ;save v0 to v6 to stack height in ram (not needed, already #1a) LD V9, #00 ;init vars: stone state LD V8, #01 ;used for xoring stone state LD Vb, #00 ;horiz. position LD Vd, #0f ;x position for selector line LD Ve, #1f ;y position for selector line LD I, vertLine ;load vert. line sprite LD V0, #0d ;xpos for left vert. line LD V1, #32 ;xpos for right vert. line LD V2, #00 ;initial pos for vert. line ypos drawLoop: DRW V0, V2, #f ;draw left line part DRW V1, V2, #f ;draw right line part ADD V2, #0f ;add to xpos for second part of line SE V2, #1e ;if xpos is not at end of large line segment... JP drawLoop ;loop DRW V0, V2, #1 ;draw left line bottom part DRW V1, V2, #1 ;draw right line bottom part ADD V2, #01 ;go 1 line down in xpos LD V0, #0a ;load ypos for "foot" LD I, areaFoot ;load "foot" sprite DRW V0, V2, #1 ;draw left area "foot" DRW V1, V2, #1 ;draw right area "foot" LD I, areaFoot ;load same sprite again DRW Vd, Ve, #1 ;draw line for position selector mainLoop: LD Vc, K ;wait for user input DRW Vd, Ve, #1 ;remove position line again SNE Vc, #05 ;if key pressed is 5 (place stone)... JP dropStone ;drop a stone SE Vc, #04 ;if key pressed is not 4 (left) or 5... JP rightElse ;jump away ADD Vb, #ff ;decrease horiz. position by adding 2's complement of 1 ADD Vd, #fb ;decrease draw position for line/stone by 5 by adding 2's complement SE Vd, #0a ;if position is not before beginning... JP drawMoved ;draw line again, don't loop position LD Vb, #06 ;set horiz. position to end LD Vd, #2d ;set draw position for line/stone to end JP drawMoved ;draw line again rightElse: SE Vc, #06 ;if key pressed is not 6 (right)... JP doNothing ;do nothing ADD Vb, #01 ;increase horiz. position ADD Vd, #05 ;add 5 to draw position for line/stone SE Vd, #32 ;if position is not past end... JP drawMoved ;don't reset position LD Vb, #00 ;reset horiz. position to 0 LD Vd, #0f ;reset draw position for line/stone drawMoved: DRW Vd, Ve, #1 ;draw selector line JP mainLoop ;go back to beginning dropStone: LD I, stnState ;load stack state base address ADD I, Vb ;add horiz. position to I for right stack state LD V0, [I] ;load it in V0 SNE V0, #fc ;if stack is at top of screen... JP doNothing ;do nothing LD Va, V0 ;backup location to draw in Va ADD V0, #fb ;subtract 5 by adding the 2's complement LD [I], V0 ;change ram at stack state to stone stack height XOR V9, V8 ;change state of stone LD I, blackStn ;load black stone sprite SE V9, #00 ;if stone state is not black... LD I, whiteStn ;load white stone sprite DRW Vd, Va, #4 ;draw stone doNothing: LD I, areaFoot ;load selector sprite DRW Vd, Ve, #1 ;draw selector line again JP mainLoop ;go back to beginning blackStn: #60 ;01100000 top of black stone areaFoot: #f0 ;11110000 "foot" of area, selector and t-m of black stone #f0 ;11110000 b-m of black stone whiteStn: #60 ;01100000 top of white stone, bottom of black stone #90 ;10010000 rest of white stone #90 ;10010000 #60 ;01100000 vertLine: #80 ;10000000 #80 ; #80 ; #80 ; #80 ; #80 ; #80 ; #80 ;bytes for vertical line sprite, used for walls #80 ; #80 ; #80 ; #80 ; #80 ; #80 ; #80 ; stnState: #1a ; #1a ; #1a ;stack state, overwritten during play #1a ; #1a ; #1a ; #1a ; stnStart: #1a ; #1a ; #1a ;initial stack state #1a ; #1a ; #1a ; #1a ; ;end of rom ;;;;;;;;;;; ; MISSILE ; ;;;;;;;;;;; JP start ;start game #4D ;"MISSILE by David WINTER" #49 ; #53 ; #53 ; #49 ; #4C ; #45 ; #20 ; #62 ; #79 ; #20 ; #44 ; #61 ; #76 ; #69 ; #64 ; #20 ; #57 ; #49 ; #4E ; #54 ; #45 ; #52 ; start: LD Vc, #0c ;init vars: wait time LD V0, #00 ;xpos for drawing LD V1, #00 ;ypos for drawing LD V5, #08 ;targets left LD V6, #0a ;rounds left LD V7, #00 ;score LD Ve, #01 ;direction LD I, target ;load target sprite drawLoop: DRW V0, V1, #4 ;draw target ADD V0, #08 ;increase xpos SE V0, #40 ;if xpos is not past end... JP drawLoop ;loop LD V0, #00 ;set xpos for ship LD V1, #1c ;set ypos for ship LD I, ship ;load ship sprite DRW V0, V1, #4 ;draw ship mainLoop: LD I, ship ;load ship again (?) DRW V0, V1, #4 ;remove ship SE Ve, #01 ;if direction is not 1... JP goLeft ;go left, else go right ADD V0, #04 ;increase xpos for ship SNE V0, #38 ;if xpos is at end... LD Ve, #00 ;set direction to 0 JP startWait ;continue goLeft: ADD V0, #fc ;decrease xpos for ship SNE V0, #00 ;if xpos is at beginning... LD Ve, #01 ;set direction to 1 startWait: DRW V0, V1, #4 ;draw ship again LD DT, Vc ;load wait time in timer waitLoop: LD Vb, DT ;get wait timer SE Vb, #00 ;if wait timer is not at 0... JP waitLoop ;loop LD V2, #08 ;load key in V2 SKP V2 ;if 8 is not pressed... JP doNothing ;jump away SE Vc, #00 ;if time to wait is not 0... ADD Vc, #fe ;decrease it by 2 LD V3, #1b ;load ypos for bullet LD V2, V0 ;get xpos for bullet from ship LD I, ship ;load sprite DRW V2, V3, #1 ;draw bullet LD V4, #00 ;load hit detector bulletLoop: DRW V2, V3, #1 ;remove bullet ADD V3, #ff ;decrease ypos by 1 DRW V2, V3, #1 ;draw bullet SE Vf, #00 ;if collision on that draw... LD V4, #01 ;detect hit SE V3, #03 ;if ypos is not at top... JP bulletLoop ;loop DRW V2, V3, #1 ;draw bullet again SE V4, #01 ;if there is no hit... JP endRound ;end round ADD V7, #05 ;increase score ADD V5, #ff ;decrease targets left LD V2, V0 ;backup xpos for ship LD V3, #00 ;set ypos for bullet at 0 LD I, target ;load target sprite DRW V2, V3, #4 ;remove target SNE V5, #00 ;if no targets left... JP endGame ;end game endRound: ADD V6, #ff ;decrease rounds left SE V6, #00 ;if still rounds left... doNothing: JP mainLoop ;jump back endGame: LD I, #2b4 ;use empty ram LD B, V7 ;put bcd for score there LD V2, [I] ;load it in V0-V2 LD V3, #1b ;load xpos for score number LD V4, #0d ;load ypos LD F, V1 ;load font for second character in I DRW V3, V4, #5 ;draw number ADD V3, #05 ;change xpos to second position LD F, V2 ;load font for third character in I DRW V3, V4, #5 ;draw second number infLoop: JP infLoop ;go in a infinte loop target: #10 ;00010000 target sprite #38 ;00111000 #38 ;00111000 ship: #10 ;00010000 bottom of target, top of ship #38 ;00111000 rest of ship sprite #7c ;01111100 #fe ;11111110 ;end of rom ;;;;;;;;;; ; TETRIS ; ;;;;;;;;;; LD I, dotSpr ;load dot sprite CALL initVars ;init vars CALL initMore ;init more vars bottomLoop: ADD V0, #01 ;increase xpos for bottom wall DRW V0, V1, #1 ;draw bottom wall SE V0, #25 ;if not done drawing bottom wall... JP bottomLoop ;loop sideLoop: ADD V1, #ff ;decrease ypos for wall DRW V0, V1, #1 ;draw right wall LD V0, #1a ;xpos for left wall DRW V0, V1, #1 ;draw left wall LD V0, #25 ;xpos for right wall SE V1, #00 ;if not at top of screen... JP sideLoop ;loop dropBlock: RND V4, #70 ;generate random value: 00, 10, 20, 30, 40, 50, 60 or 70, block type SNE V4, #70 ;if value/block type is 70... JP dropBlock ;generate another RND V3, #03 ;generate random value: 00, 01, 02 or 03, rotation? LD V0, #1e ;xpos for block LD V1, #03 ;ypos for block CALL getBlock ; get sprite for block mainLoop: LD DT, V5 ;load timer with time DRW V0, V1, #4 ;draw block SE Vf, #01 ;if no collision on that draw... JP waitLoop ;go to wait loop / get input DRW V0, V1, #4 ;else, remove block ADD V1, #ff ;subtract 1 from xpos DRW V0, V1, #4 ;draw it again CALL lineCheck ;check for lines JP dropBlock ;drop new block waitLoop: SKNP V7 ;if key for left is pressed (5)... CALL moveLeft ;move left SKNP V8 ;if key for right is pressed (6)... CALL moveRight ;move right SKNP V9 ;if key for turn is pressed (4)... CALL turnBlock ;turn block SKP V2 ;if key for quick-fall is not pressed (7)... JP waitStart ;jump to timer check LD V6, #00 ;load 0 in V6 LD DT, V6 ;load timer with it waitStart: LD V6, DT ;load timer in V6 SE V6, #00 ;if timer is not 0... JP waitLoop ;loop for input again DRW V0, V1, #4 ;remove block ADD V1, #01 ;increase ypos JP mainLoop ;loop getBlock: LD I, blockSpr ;load block-sprite base address ADD I, V4 ;add block type (multiple of 16) to it LD V6, #00 ;load rotation base SNE V3, #01 ;if rotation is 1... LD V6, #04 ;set rotation to add to 4 SNE V3, #02 ;if rotation is 2... LD V6, #08 ;set rotation to add to 8 SNE V3, #03 ;if rotation is 3... LD V6, #0c ;set rotation to add to 0xc ADD I, V6 ;add rotation type times 4 to address RET ;return moveLeft: DRW V0, V1, #4 ;remove block ADD V0, #ff ;decrease xpos by one CALL drawWait ;draw and wait SE Vf, #01 ;if no collision on that draw... RET ;return DRW V0, V1, #4 ;else, remove block ADD V0, #01 ;increase xpos again CALL drawWait ;draw and wait RET ;return moveRight: DRW V0, V1, #4 ;remove block ADD V0, #01 ;increase xpos CALL drawWait ;draw and wait SE Vf, #01 ;if no collision on that draw... RET ;return DRW V0, V1, #4 ;else, remove block ADD V0, #ff ;decrease xpos again CALL drawWait ;draw and wait RET ;return turnBlock: DRW V0, V1, #4 ;remove block ADD V3, #01 ;add 1 to rotation SNE V3, #04 ;if rotation is past 3... LD V3, #00 ;set it back to 0 CALL getBlock ;get new block sprite CALL drawWait ;draw and wait SE Vf, #01 ;if no collision on that turn... RET ;return DRW V0, V1, #4 ;remove block ADD V3, #ff ;subtract 1 from rotation SNE V3, #ff ;if rotation is before 0... LD V3, #03 ;set it back to 3 CALL getBlock ;get new block sprite CALL drawWait ;draw and wait RET ;return dotSpr: #80 ;10000000 dot for walls and checks #00 ;unused byte (probably for alignment to even address) initMore: LD V7, #05 ;key for left LD V8, #06 ;key for right LD V9, #04 ;key for turning LD V1, #1f ;ypos for wall drawing LD V5, #10 ;initial wait time LD V2, #07 ;key for quick-fall RET ;return blockSpr: #40 ;01000000 block 0, rot 0 #e0 ;11100000 #00 ;00000000 #00 ;00000000 #40 ;01000000 block 0, rot 1 #c0 ;11000000 #40 ;01000000 #00 ;00000000 #00 ;00000000 block 0, rot 2 #e0 ;11100000 #40 ;01000000 #00 ;00000000 #40 ;01000000 block 0, rot 3 #60 ;01100000 #40 ;01000000 #00 ;00000000 #40 ;01000000 block 1, rot 0 #40 ;01000000 #60 ;01100000 #00 ;00000000 #20 ;00100000 block 1, rot 1 #e0 ;11100000 #00 ;00000000 #00 ;00000000 #c0 ;11000000 block 1, rot 2 #40 ;01000000 #40 ;01000000 #00 ;00000000 #00 ;00000000 block 1, rot 3 #e0 ;11100000 #80 ;10000000 #00 ;00000000 #40 ;01000000 block 2, rot 0 #40 ;01000000 #c0 ;11000000 #00 ;00000000 #00 ;00000000 block 2, rot 1 #e0 ;11100000 #20 ;00100000 #00 ;00000000 #60 ;01100000 block 2, rot 2 #40 ;01000000 #40 ;01000000 #00 ;00000000 #80 ;10000000 block 2, rot 3 #e0 ;11100000 #00 ;00000000 #00 ;00000000 #40 ;01000000 block 3, rot 0 #c0 ;11000000 #80 ;10000000 #00 ;00000000 #c0 ;11000000 block 3, rot 1 #60 ;01100000 #00 ;00000000 #00 ;00000000 #40 ;01000000 block 3, rot 2 #c0 ;11000000 #80 ;10000000 #00 ;00000000 #c0 ;11000000 block 3, rot 3 #60 ;01100000 #00 ;00000000 #00 ;00000000 #80 ;10000000 block 4, rot 0 #c0 ;11000000 #40 ;01000000 #00 ;00000000 #00 ;00000000 block 4, rot 1 #60 ;01100000 #c0 ;11000000 #00 ;00000000 #80 ;10000000 block 4, rot 2 #c0 ;11000000 #40 ;01000000 #00 ;00000000 #00 ;00000000 block 4, rot 3 #60 ;01100000 #c0 ;11000000 #00 ;00000000 #c0 ;11000000 block 5, rot 0 #c0 ;11000000 #00 ;00000000 #00 ;00000000 #c0 ;11000000 block 5, rot 1 #c0 ;11000000 #00 ;00000000 #00 ;00000000 #c0 ;11000000 block 5, rot 2 #c0 ;11000000 #00 ;00000000 #00 ;00000000 #c0 ;11000000 block 5, rot 3 #c0 ;11000000 #00 ;00000000 #00 ;00000000 #40 ;01000000 block 6, rot 0 #40 ;01000000 #40 ;01000000 #40 ;01000000 #00 ;00000000 block 6, rot 1 #f0 ;11110000 #00 ;00000000 #00 ;00000000 #40 ;01000000 block 6, rot 2 #40 ;01000000 #40 ;01000000 #40 ;01000000 #00 ;00000000 block 6, rot 3 #f0 ;11110000 #00 ;00000000 #00 ;00000000 drawWait: DRW V0, V1, #4 ;draw block again LD V6, #35 ;load quick-wait time quickWait: ADD V6, #ff ;subtract 1 from time SE V6, #00 ;if it is not 0... JP quickWait ;loop RET ;return lineCheck: LD I, dotSpr ;load dot sprite LD Vc, V1 ;load ypos in Vc (when to stop checking) SE Vc, #1e ;if it is not at bottom... ADD Vc, #01 ;increase it by one SE Vc, #1e ;if it is not at bottom... ADD Vc, #01 ;increase it by one SE Vc, #1e ;if it is not at bottom... ADD Vc, #01 ;increase it by one checkLoop: CALL singleLCh ;check line SNE Vb, #0a ;if counter is at 10, all dots filled... CALL clearLine ;clear the line SNE V1, Vc ;if cur ypos is at end for checking... RET ;return ADD V1, #01 ;increase ypos JP checkLoop ;loop singleLCh: LD V0, #1b ;load line start xpos LD Vb, #00 ;reset check counter lineChLoop: DRW V0, V1, #1 ;draw dot for checking SE Vf, #00 ;if collision on that draw... ADD Vb, #01 ;increase check counter DRW V0, V1, #1 ;remove dot again ADD V0, #01 ;increase xpos SE V0, #25 ;if not at end... JP lineChLoop ;loop RET ;else, return clearLine: LD V0, #1b ;load line start in xpos clLnLoop: DRW V0, V1, #1 ;remove dot ADD V0, #01 ;increase xpos SE V0, #25 ;if xpos is not at end... JP clLnLoop ;loop LD Ve, V1 ;load ypos in Ve (for checking above) LD Vd, Ve ;load it in Vd as well (for moving down) ADD Ve, #ff ;decrease ypos for checking by one moveLoop: LD V0, #1b ;load line start in xpos LD Vb, #00 ;reset dots moved moveLnLoop: DRW V0, Ve, #1 ;draw check dot SE Vf, #00 ;if collision on that draw... JP moveDot ;move the dot DRW V0, Ve, #1 ;remove check dot again JP noMove ;do not move dot moveDot: DRW V0, Vd, #1 ;draw dot in new position ADD Vb, #01 ;increase dots moved noMove: ADD V0, #01 ;increase xpos SE V0, #25 ;if xpos is not at end... JP moveLnLoop ;loop SNE Vb, #00 ;if no dots moved (done moving)... JP finishMove ;finish the moving ADD Vd, #ff ;decrease ypos for moving ADD Ve, #ff ;decrease ypos for checking SE Vd, #01 ;if ypos for moving is not at top of screen... JP moveLoop ;loop finishMove: CALL doScore ;do the score (remove old one, draw it when first time) SE Vf, #01 ;if no collision when drawing score (first time) CALL doScore ;do it again (remove it) ADD Va, #01 ;increase score CALL doScore ;draw new score LD V0, Va ;load score in V0 LD Vd, #07 ;load value for ANDing AND V0, Vd ;AND score with 7 (mod 8) SNE V0, #04 ;if it is 4 (each 8 lines)... ADD V5, #fe ;decrease wait time by 2 SNE V5, #02 ;if wait time is 2... LD V5, #04 ;set it back to 4 RET ;return doScore: LD I, #700 ;use empty ram LD [I], V2 ;backup V0-V2 there LD I, #804 ;use different ram LD B, Va ;put bcd for score there LD V2, [I] ;load it in V0-V2 LD F, V0 ;load font sprite for first digit LD Vd, #32 ;load xpos LD Ve, #00 ;load ypos DRW Vd, Ve, #5 ;draw first digit ADD Vd, #05 ;increase xpos LD F, V1 ;load sprite for second digit DRW Vd, Ve, #5 ;draw it ADD Vd, #05 ;increase xpos LD F, V2 ;load sprite for third digit DRW Vd, Ve, #5 ;draw it LD I, #700 ;get ram for backup LD V2, [I] ;load it back in V0-V2 LD I, dotSpr ;load dot sprite again RET ;return initVars: LD Va, #00 ;score LD V0, #19 ;initial xpos for bottom wall - 1 RET ;return #37 ;unused bytes, unknown use #23 ; ;end of rom